/*Author: Rony Lahav (ID:043489889)*/

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;


/** Used for printing log messages to output file**/

public class Logger {
	
	private ArrayList<String> filterIM;
	private ArrayList<String> filterFT;
	
	private boolean dontWrite=false; //if an output file needs to be sent - the file is closed and no more printing will be done
	
	private static Logger logger = null;
	static PrintWriter pw; 
	
	//opens output file
	private Logger() throws IOException{
		pw = new PrintWriter(new FileWriter(final_project.outputFilePath));
	}
	
	//singleton
	public static Logger getInstance()
	{
		try {
			if (logger == null) {
				logger = new Logger();
			}
		}
		catch(IOException e) {
		}
		return logger;
	}
	
	//prints an ERROR message including peer ID and IP
	public synchronized HashMap<String,String> printErrorMessage(String msgHeader, String msgType, String peerID, String peerIP) {
		if (!dontWrite && !final_project.isShutDown()){
			StringBuilder sb = new StringBuilder();
			sb.append(msgHeader+"; ");
			sb.append("Type: ");
			if (msgType == null || msgType == "")
				sb.append("Unknown; ");
			else
				sb.append(msgType+"; ");
			sb.append("ID: ");
			if (peerID == null || peerID == "")
				sb.append("Unknown; ");
			else
				sb.append(peerID+"; ");
			sb.append("IP: ");
			if (peerIP == null || peerIP == "")
				sb.append("Unknown");
			else
				sb.append(peerIP);
			//sb.append(MessageCenter.newline);
			pw.println(sb);
			pw.flush();
		}
		return null;
	}
	
	//prints an INCOMING message that passes the filter
	@SuppressWarnings("unchecked")
	public synchronized void printIncomingMsg(String type, String msg, String peerID, String peerIP) {
		if (!dontWrite && !final_project.isShutDown()){
			boolean printed = false;
			if (type.equals(MessageCenter.TYPE_IM)){
				if (isFilterIMEmpty())
					printMsg(type, msg, peerID, peerIP);
				else
					for (Iterator iterator = filterIM.iterator(); !printed && iterator.hasNext();) {
						String filter = (String) iterator.next();
						if (msg.startsWith(filter)){
							printed=true;
							printMsg(type, msg, peerID, peerIP);
						}
					}
			}
			else if (type.equals(MessageCenter.TYPE_FT)){
				if (isFilterFTEmpty())
					printMsg(type, msg, peerID, peerIP);
				else
					for (Iterator iterator = filterFT.iterator(); !printed && iterator.hasNext();) {
						String filter = (String) iterator.next();
						if (msg.startsWith(filter)){
							printed=true;
							printMsg(type, msg, peerID, peerIP);
						}
					}
			}
			else if (type.equals(MessageCenter.TYPE_GET))	//AV messages are not pronted
				printMsg(type, msg, peerID, peerIP);
		}
	}
	
	//prints the message if in filter
	private synchronized void printMsg(String type, String msg, String peerID, String peerIP) {
		if (!dontWrite && !final_project.isShutDown()){
			StringBuilder sb = new StringBuilder();
	
			sb.append(type + ": " + msg + "; ");
			sb.append("ID" + ": " + peerID + "; ");
			sb.append("IP" + ": " + peerIP);
			//sb.append(MessageCenter.newline);
			
			pw.println(sb);
			pw.flush();
		}
	}
	
	//prints an AT message
	public synchronized HashMap<String,String> printATMsg(int time) {
		if (!dontWrite && !final_project.isShutDown()){
			StringBuilder sb = new StringBuilder();
	
			sb.append("AT" + ": " + Integer.toString(time));
			//sb.append(MessageCenter.newline);
			
			pw.println(sb);
			pw.flush();
		}
		return null;
	}
	
	//prints free text for debugging
	public synchronized void printFreeText(String msg) {
		StringBuilder sb = new StringBuilder();
		sb.append(msg);
		//sb.append(MessageCenter.newline);
		
		pw.println(sb);
		pw.flush();
	}
	
	public void close(){
		if (pw!=null)
			pw.close();
	}
	
	public synchronized boolean isFilterIMEmpty(){
		if (filterIM==null)
			return true;
		else
			return false;
	}
	
	public synchronized boolean isFilterFTEmpty(){
		if (filterFT==null)
			return true;
		else
			return false;
	}
	
	public synchronized void addFilterIM(String filter){
		if (filterIM==null)
			filterIM=new ArrayList<String>();
		filterIM.add(filter);
	}
	
	public synchronized void addFilterFT(String filter){
		if (filterFT==null)
			filterFT=new ArrayList<String>();
		filterFT.add(filter);
	}
	
	//if an output file needs to be sent - the file is closed and no more printing will be done
	public synchronized void closeFileAndStopWriting(){
		dontWrite=true;
		if (pw!=null){
			pw.close();
			pw=null;
			copyOutputFileToFilesDirectory();
		}
	}
	
	private void copyOutputFileToFilesDirectory() {
		File fromFile = new File(final_project.outputFilePath);
	    File toFile = new File(final_project.currentDir+"/files/"+final_project.outputFilePath);
	    FileInputStream fromBuffer = null;
	    FileOutputStream toBuffer = null;
	    try {
	      fromBuffer = new FileInputStream(fromFile);
	      toBuffer = new FileOutputStream(toFile);
	      byte[] buffer = new byte[1024];
	      int bytesRead;
	      while ((bytesRead = fromBuffer.read(buffer)) != -1)
	        toBuffer.write(buffer, 0, bytesRead); // write
	    } catch (IOException e) {}
	    finally {
	      if (fromBuffer != null)
	        try {
	          fromBuffer.close();
	        } catch (IOException e) {}
	      if (toBuffer != null)
	        try {
	          toBuffer.close();
	        } catch (IOException e) {}
	    }
	}
	
}
